package server.core;

import server.*;
import server.util.LifecycleSupport;
import sun.plugin.viewer.LifeCycleManager;

import javax.servlet.ServletException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;


public abstract class ContainerBase implements Container, Lifecycle, Pipeline {
    //实现不完整的方法-------------------------------------------------------------------
    @Override
    public synchronized void start() throws LifecycleException {
        if (started)
            throw new LifecycleException("Container {" + logName() + "} has already been started");
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
//        addDefaultMapper(this.mapperClass);
        started = true;

        //启动组件
        if (loader != null && loader instanceof Lifecycle)
            ((Lifecycle) loader).start();
        if (logger != null && logger instanceof  Lifecycle)
            ((Lifecycle) logger).start();
//        if ((manager != null) && (manager instanceof Lifecycle))
//            ((Lifecycle) manager).start();
//        if ((cluster != null) && (cluster instanceof Lifecycle))
//            ((Lifecycle) cluster).start();
//        if ((realm != null) && (realm instanceof Lifecycle))
//            ((Lifecycle) realm).start();
//        if ((resources != null) && (resources instanceof Lifecycle))
//            ((Lifecycle) resources).start();
//        Mapper mappers[] = findMappers();
//        for (int i = 0; i < mappers.length; i++) {
//            if (mappers[i] instanceof Lifecycle)
//                ((Lifecycle) mappers[i]).start();
//        }
        Container[] children = findChildren();
        for (Container container : children) {
            if (container instanceof Lifecycle)
                ((Lifecycle) container).start();
        }
        if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();

        lifecycle.fireLifecycleEvent(START_EVENT, null);
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }

    @Override
    public void stop() throws LifecycleException {
        if (!started)
            throw new LifecycleException("Container {" + logName() + "} has not been started");
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).stop();
        }
        Container[] children = findChildren();
        for (Container container : children) {
            if (container instanceof Lifecycle)
                ((Lifecycle) container).stop();
        }

//        Mapper mappers[] = findMappers();
//        for (int i = 0; i < mappers.length; i++) {
//            if (mappers[(mappers.length-1)-i] instanceof Lifecycle)
//                ((Lifecycle) mappers[(mappers.length-1)-i]).stop();
//        }
//        if ((resources != null) && (resources instanceof Lifecycle)) {
//            ((Lifecycle) resources).stop();
//        }
//        if ((realm != null) && (realm instanceof Lifecycle)) {
//            ((Lifecycle) realm).stop();
//        }
//        if ((cluster != null) && (cluster instanceof Lifecycle)) {
//            ((Lifecycle) cluster).stop();
//        }
//        if ((manager != null) && (manager instanceof Lifecycle)) {
//            ((Lifecycle) manager).stop();
//        }
        if (logger != null && logger instanceof Lifecycle) {
            ((Lifecycle) logger).stop();
        }
        if (loader != null && loader instanceof Lifecycle) {
            ((Lifecycle) loader).stop();
        }
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
    }
    //属性--------------------------------------------------------------------------

    //生命周期工具类
    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
    //加载器
    protected Loader loader = null;
    //日志记录器
    protected Logger logger = null;
    //管道
    protected Pipeline pipeline = new StandardPipeline(this);
    //父容器
    protected Container parent = null;
    //容器是否启动
    protected boolean started = false;
    //容器名
    protected String name = null;
    //子容器
    protected HashMap<String, Container> children = new HashMap<>();
    protected int debug = 0;
    //存放映射器
    protected HashMap<String, Mapper> mappers = new HashMap<>();
    protected Manager manager = null;
    //该类的方法--------------------------------------------------------------------------
    //打日志
    protected void log(String message) {
        Logger logger = getLogger();
        if (logger != null)
            logger.log(logName() + ": " + message);
        else
            System.out.println(logName() + ": " + message);
    }
    //打日志
    protected void log(String message, Throwable throwable) {
        Logger logger = getLogger();
        if (logger != null)
            logger.log(logName() + ": " + message, throwable);
        else {
            System.out.println(logName() + ": " + message + ": " + throwable);
            throwable.printStackTrace(System.out);
        }
    }
    //获取打印名(类名[容器名])
    protected String logName() {
        String className = this.getClass().getName();
        int index = className.lastIndexOf(".");
        if (index >= 0) {
            className = className.substring(index + 1);
        }
        return className + "[" + getName() + "]";
    }

    public int getDebug() {
        return debug;
    }

    //添加默认映射器,映射器全类名为mapperClass
    protected void addDefaultMapper(String mapperClass) {
        if (mapperClass == null)
            return;
        //如果存在映射器,不需要添加默认映射器
        if (mappers.size() >= 1)
            return;
        try {
            Class clazz = Class.forName(mapperClass);
            Mapper mapper = (Mapper) clazz.newInstance();
            mapper.setProtocol("http");
            addMapper(mapper);
        } catch (Exception e) {
            log("Exception configuring default mapper of class {" + mapperClass + "}");
        }

    }
    //实现Container接口-------------------------------------------------------------------
    @Override
    public abstract String getInfo();

    //获取本容器的加载器，如果本容器的加载器为空且父类不为空，获取父类的加载器
    @Override
    public Loader getLoader() {
        if (loader != null)
            return loader;
        if (parent != null)
            return parent.getLoader();
        return null;
    }
    //设置加载器
    @Override
    public synchronized void setLoader(Loader loader) {
        Loader oldLoader = this.loader;
        if (oldLoader == loader)
            return;
        this.loader = loader;
        //如果容器已经启动(容器启动方法会启动其loader),关闭旧loader
        if (started && oldLoader != null && oldLoader instanceof Lifecycle) {
            try {
                ((Lifecycle) oldLoader).stop();
            } catch (LifecycleException e) {
                log("ContainerBase.setLoader: stop: ", e);
            }
        }
        //将加载器关联到本容器
        if (loader != null)
            loader.setContainer(this);
        //如果容器已经启动,启动新loader
        if (started && loader != null && loader instanceof Lifecycle) {
            try {
                ((Lifecycle) loader).start();
            } catch (LifecycleException e) {
                log("ContainerBase.setLoader: start: ", e);
            }
        }
    }

    //获取本容器的日志记录器，如果本容器的记录器为空且父类不为空，获取父类的记录器
    @Override
    public Logger getLogger() {
        if (logger != null)
            return logger;
        if (parent != null)
            return parent.getLogger();
        return null;
    }

    //设置日志记录器
    @Override
    public synchronized void setLogger(Logger logger) {
        Logger oldLogger = this.logger;
        if (oldLogger == logger)
            return;
        this.logger = logger;
        //如果容器已经启动(容器启动方法会启动其logger),关闭旧logger
        if (started && oldLogger != null && oldLogger instanceof Lifecycle) {
            try {
                ((Lifecycle) oldLogger).stop();
            } catch (LifecycleException e) {
                log("ContainerBase.setLogger: stop: ", e);
            }
        }
        //将日志器关联到本容器
        if (logger != null)
            logger.setContainer(this);
        //如果容器已经启动,启动新logger
        if (started && logger != null && logger instanceof Lifecycle) {
            try {
                ((Lifecycle) logger).start();
            } catch (LifecycleException e) {
                log("ContainerBase.setLogger: start: ", e);
            }
        }
    }

    @Override
    public Container map(Request request, boolean update) {
        Mapper mapper = findMapper(request.getRequest().getProtocol());
        if (mapper == null)
            return null;
        return mapper.map(request, update);
    }

    @Override
    public Mapper findMapper(String protocol) {
        synchronized (mappers) {
            //只有一个映射器,直接返回
            if (mappers.size() == 1) {
                return mappers.values().iterator().next();
            }
            return mappers.get(protocol);
        }
    }

    @Override
    public Mapper[] findMappers() {
        synchronized (mappers){
            Mapper[] mapperArr = new Mapper[mappers.size()];
            return mappers.values().toArray(mapperArr);
        }
    }

    @Override
    public void addMapper(Mapper mapper) {
        synchronized (mappers) {
            //一个协议只能有唯一对应的mapper
            if (mappers.get(mapper.getProtocol()) != null) {
                throw new IllegalArgumentException("addMapper:  Protocol '" + mapper.getProtocol() + "' is not unique");
            }
            mapper.setContainer(this);
            if (started && mapper instanceof Lifecycle) {
                try {
                    ((Lifecycle) mapper).start();
                } catch (LifecycleException e) {
                    log("ContainerBase.addMapper: start: ", e);
                    throw new IllegalStateException("ContainerBase.addMapper: start: " + e);
                }
            }
            mappers.put(mapper.getProtocol(), mapper);
        }
    }

    @Override
    public void removeMapper(Mapper mapper) {
        synchronized (mappers) {
            //找不到直接返回
            if (mappers.get(mapper.getProtocol()) == null)
                return;
            mappers.remove(mapper.getProtocol());
            if (started && mapper instanceof Lifecycle) {
                try {
                    ((Lifecycle) mapper).stop();
                } catch (LifecycleException e) {
                    log("ContainerBase.removeMapper: stop: ", e);
                    throw new IllegalStateException("ContainerBase.removeMapper: stop: " + e);
                }
            }
        }
    }

    //获取容器名
    @Override
    public String getName() {
        return name;
    }

    //设置容器名
    @Override
    public void setName(String name) {
        this.name = name;
    }

    //获取父容器
    @Override
    public Container getParent() {
        return parent;
    }

    //设置父容器
    @Override
    public void setParent(Container parent) {
        this.parent = parent;
    }

    //添加子容器
    @Override
    public void addChild(Container child) {
        synchronized (children) {
            //子容器中已经存在该容器名,无法添加
            if (children.containsKey(child.getName())) {
                throw new IllegalArgumentException("addChild:  Child name '" + child.getName() + "' is not unique");
            }
            //如果容器已经启动,启动新加入的子容器
            if (started && child instanceof Lifecycle) {
                try {
                    ((Lifecycle) child).start();
                } catch (LifecycleException e) {
                    log("ContainerBase.addChild: start: ", e);
                    throw new IllegalStateException("ContainerBase.addChild: start: " + e);
                }
            }
            child.setParent(this);
            children.put(child.getName(), child);
        }
    }

    //删除子容器
    @Override
    public void removeChild(Container child) {
        if (child == null)
            return;
        synchronized (children) {
            if (!children.containsKey(child.getName()))
                return;
            children.remove(child.getName());
        }
        if (started && child instanceof Lifecycle) {
            try {
                ((Lifecycle) child).stop();
            } catch (LifecycleException e) {
                log("ContainerBase.removeChild: stop: ", e);
            }
        }
        child.setParent(null);
    }

    //根据子容器名查找子容器
    @Override
    public Container findChild(String name) {
        synchronized (children) {
            return children.get(name);
        }
    }

    //查找所有子容器
    @Override
    public Container[] findChildren() {
        synchronized (children) {
            Container[] containers = new Container[children.size()];
            return children.values().toArray(containers);
        }
    }

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        pipeline.invoke(request, response);
    }

    @Override
    public Manager getManager() {
        if (manager != null)
            return manager;
        if (parent != null)
            return parent.getManager();
        return null;
    }

    @Override
    public synchronized void setManager(Manager manager) {
        Manager oldManager = this.manager;
        if (oldManager == manager)
            return;
        this.manager = manager;
        if (started && oldManager != null) {
            if (oldManager instanceof Lifecycle) {
                try {
                    ((Lifecycle) oldManager).stop();
                } catch (LifecycleException e) {
                    log("暂停旧的Session管理器失败", e);
                }
            }
        }
        if (manager != null) {
            manager.setContainer(this);
        }
        if (started && manager != null && manager instanceof Lifecycle) {
            try {
                ((Lifecycle) manager).start();
            } catch (LifecycleException e) {
                log("启动新的Session管理器失败", e);
            }
        }

    }

    //实现Lifecycle接口-------------------------------------------------------------------
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }

    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    //实现Pipeline接口-------------------------------------------------------------------

    @Override
    public synchronized void addValve(Valve valve) {
        pipeline.addValve(valve);
    }

    @Override
    public Valve getBasic() {
        return pipeline.getBasic();
    }

    @Override
    public List<Valve> getValves() {
        return pipeline.getValves();
    }

    @Override
    public synchronized void removeValve(Valve valve) {
        pipeline.removeValve(valve);
    }

    @Override
    public void setBasic(Valve valve) {
        pipeline.setBasic(valve);
    }
}
